package cn.sylinx.web.util;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public class ClasspathResourceScanner {

	private String path;

	private String postfix;

	public ClasspathResourceScanner(String path) {
		this(path, null, false, null);
	}

	public ClasspathResourceScanner(String path, boolean isPackage) {
		this(path, null, isPackage);
	}

	public ClasspathResourceScanner(String path, String postfix) {
		this(path, postfix, false);
	}

	public ClasspathResourceScanner(String path, String postfix, boolean isPackage) {
		this(path, postfix, isPackage, null);
	}

	public ClasspathResourceScanner(String path, String postfix, boolean isPackage, ClassLoader cl) {

		this.path = path;
		this.postfix = postfix;

		if (this.postfix == null) {
			this.postfix = ".xml";
		}

		// 如果是包名，则转换成folder路径
		if (isPackage) {
			this.path = path.replaceAll("\\.", "/");
		}

	}

	public List<String> getResourceNameList() throws Exception {

		return doScan(path, new ArrayList<String>());
	}

	private List<String> doScan(String baseFolder, List<String> nameList) throws Exception {

		URL url = Resources.getResourceURL(baseFolder);
		String filePath = StringUtil.getRootPath(url);

		List<String> names = null;

		boolean isJarFile = isJarFile(filePath);
		if (isJarFile) {
			names = readFromJarFile(filePath, baseFolder);
		} else {
			names = readFromDirectory(filePath);
		}

		if (names == null) {
			return null;
		}

		for (String name : names) {

			if (isMatchFile(name)) {

				if (isJarFile) {
					nameList.add(name);
				} else {
					nameList.add(baseFolder + "/" + name);
				}

			} else {
				doScan(baseFolder + "/" + name, nameList);
			}
		}

		return nameList;
	}

	private boolean isJarFile(String name) {

		return name.endsWith(".jar");
	}

	private boolean isMatchFile(String name) {
		return name.endsWith(postfix);
	}

	private List<String> readFromDirectory(String path) {

		File f = new File(path);
		String[] names = f.list();

		if (names == null) {
			return null;
		}

		return Arrays.asList(names);
	}

	private List<String> readFromJarFile(String jarPath, String splashedPackageName) throws Exception {

		JarInputStream jarIn = null;

		try {

			jarIn = new JarInputStream(new FileInputStream(jarPath));

			JarEntry entry = jarIn.getNextJarEntry();

			List<String> nameList = new ArrayList<String>();

			while (entry != null) {

				String name = entry.getName();
				if (name.startsWith(splashedPackageName) && isMatchFile(name)) {
					nameList.add(name);
				}
				entry = jarIn.getNextJarEntry();
			}

			return nameList;

		} finally {

			if (jarIn != null) {

				jarIn.close();
			}
		}

	}
}
